{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Self Driving Car 2D World\n",
    "\n",
    "Here are your tasks for this set of exercises:\n",
    "* write a function that initializes probabilities across the grid\n",
    "* write a function that outputs the probability that the robot is at a specific point on the grid\n",
    "* write a function to visualize the probabilities of the grid (this function is provided for you)\n",
    "* write a function to update probabilities on the grid\n",
    "\n",
    "This set of exercises are the same as the 1D world. But now you'll need to use nested for loops and nested lists, which can be tricky."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercise 1\n",
    "\n",
    "Write a function that initializes probabilities across the 2D grid. Remember that initially, the probabilities are equal across the entire grid. And all of the probabilities need to add up to one.\n",
    "\n",
    "So if your grid was 5 by 4, you'd have 20 spaces; the initial probability associated with each space would be 1/20.\n",
    "\n",
    "Here are the inputs and outputs of the function:\n",
    "\n",
    "**Inputs**\n",
    "* the number of rows in the grid\n",
    "* the number of columns in the grid\n",
    "\n",
    "**Outputs**\n",
    "* a nested list containing the probabilities for each grid cell"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def initial_grid(rows, columns):\n",
    "\n",
    "    # TODO: initialize an empty list in a variable called grid\n",
    "    grid = []\n",
    "    \n",
    "    # TODO: initialize an empty row in a variable called row\n",
    "    row = []\n",
    "\n",
    "    # TODO: calculate the initial probability\n",
    "    probability = 0\n",
    "    \n",
    "    # TODO: write a nested for loop that appends values to the grid variable\n",
    "    # HINT: You first need to fill in a row with values and then append the row to the grid.\n",
    "    #        Then you'll need to set the row variable to an empty list.\n",
    "    #        The logic of all this can be tough to think through. \n",
    "    #        If you get stuck, see the demonstrations in the previous part of the lesson\n",
    "        \n",
    "    return grid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run the code cell below to test your results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert initial_grid(5, 4) == [[0.05, 0.05, 0.05, 0.05],\n",
    "                              [0.05, 0.05, 0.05, 0.05],\n",
    "                              [0.05, 0.05, 0.05, 0.05],\n",
    "                              [0.05, 0.05, 0.05, 0.05],\n",
    "                              [0.05, 0.05, 0.05, 0.05]]\n",
    "\n",
    "assert initial_grid(2, 5) == [[0.1, 0.1, 0.1, 0.1, 0.1], \n",
    "                              [0.1, 0.1, 0.1, 0.1, 0.1]]\n",
    "\n",
    "assert initial_grid(2, 2) == [[0.25, 0.25], \n",
    "                              [0.25, 0.25]]\n",
    "\n",
    "print('Hooray!')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercise 2\n",
    "\n",
    "Write a function that outputs the probability that the robot is at a specific point on the grid.\n",
    "\n",
    "Here are the function inputs and outputs:\n",
    "\n",
    "**Inputs**\n",
    "\n",
    "* a 2D grid given as a nested list\n",
    "* a row number\n",
    "* a column number\n",
    "\n",
    "**Outputs**\n",
    "* the probability at the input row, column\n",
    "\n",
    "**HINT**\n",
    "\n",
    "Remember that the first grid cell in row one, column one is accessed with `[0][0]` not `[1][1]`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def probability(grid, row, column):\n",
    "    \n",
    "    # TODO: return the probability that the robot as at the space representing by the row and column values.\n",
    "    \n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert probability([[.25, .1], \n",
    "                    [.45, .2]], \n",
    "                   1, 1) == 0.2\n",
    "\n",
    "assert probability([[.05, .1, .1],\n",
    "                    [.04, .3, .02],\n",
    "                    [.01, .02, .02],\n",
    "                    [.005, .012, .06],\n",
    "                    [.09, .07, .103]], 3, 2) == 0.06\n",
    "\n",
    "assert probability([[.05, .1, .1],\n",
    "                    [.04, .3, .02],\n",
    "                    [.01, .023, .017],\n",
    "                    [.005, .012, .06],\n",
    "                    [.09, .07, .103]], 2, 2) == .017\n",
    "\n",
    "print('You passed all the assertion tests.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# DEMO\n",
    "\n",
    "Run the code cell below to visualize the probabilities of the grid. This function is provided for you. We are providing this code for you since we haven't talked about how to graphically represent probability distributions in 2D.\n",
    "\n",
    "Run the code cells below to see the output. The code shows a heat map. Whereas a bar chart represented probability on the y-axis, a heat map can represent probability with color."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def graph_grid(grid):\n",
    "    plt.imshow(grid, cmap='Greys', clim=(0,.1))\n",
    "    plt.title('Heat Map of Grid Probabilities')\n",
    "    plt.xlabel('grid x axis')\n",
    "    plt.ylabel('grid y axis')\n",
    "    plt.legend()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid = [[.05, .1, .1],\n",
    "        [.04, .3, .02],\n",
    "        [.01, .023, .017],\n",
    "        [.005, .012, .06],\n",
    "        [.09, .07, .103]]\n",
    "\n",
    "graph_grid(grid)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercise 3\n",
    "\n",
    "Write a function to update probabilities on the grid. Like the 1-D case, your function will receive a coordinate and the updated probability. The updated probability coordinates will not be in any particular order; for example, the list might contain grid cell (2,5) followed by grid cell (1,7). \n",
    "\n",
    "Here are the inputs and outputs of the function.\n",
    "\n",
    "**Inputs**\n",
    "* A 2D nested list containing the probabilities that the robot is at each cell\n",
    "* A nested list containing grid cell coordinates and a new probability\n",
    "\n",
    "**Ouput**\n",
    "* A 2D nested list, representing the grid, which contains the updated robot grid probabilities\n",
    "\n",
    "\n",
    "Let's say you had a grid with the following probabilities:\n",
    "```python\n",
    "grid = [[.05, .1, .1],\n",
    "        [.04, .3, .02],\n",
    "        [.01, .023, .017],\n",
    "        [.005, .012, .06],\n",
    "        [.09, .07, .103]]\n",
    "```\n",
    "\n",
    "You receive an update list with the following values\n",
    "```python\n",
    "update_list = [\n",
    "              [[4,2], 0.012],\n",
    "              [[2,2], 0.108],\n",
    "              [[0,1], 0.004],\n",
    "              [[3,0], 0.101]\n",
    "              ]\n",
    "```\n",
    "\n",
    "The grid cell at [4,2] currently has a probability value of 0.103. Now, you'll replace the value with 0.012.\n",
    "\n",
    "The grid cell at [2,3] has the probability 0.017. \n",
    "\n",
    "Don't get intimidated by the update_list variable! It's just a nested list similar to what you've already seen. But the update_list variable is a list of list of lists.\n",
    "\n",
    "For example, [4,3] represents the grid cell in row five column three, and 0.012 representes the new probability.\n",
    "\n",
    "In the next cell, you'll find some example code with a couple of different ways to access the values in the list. Study the examples and use the examples to help you program the update_probability() function.\n",
    "\n",
    "### Nested For Loops Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Example of nested lists\n",
    "\n",
    "update_list = [\n",
    "              [[4,2], 0.012],\n",
    "              [[2,2], 0.108],\n",
    "              [[0,1], 0.004],\n",
    "              [[3,0], 0.101]\n",
    "              ]\n",
    "\n",
    "# Code for accessing the first element in the list\n",
    "print(update_list[0])\n",
    "print(update_list[0][0])\n",
    "print(update_list[0][0][0])\n",
    "print(update_list[0][0][1])\n",
    "print(update_list[0][1])\n",
    "\n",
    "# Output of for loop\n",
    "print('\\noutput of for loop')\n",
    "for element in update_list:\n",
    "    print(element)\n",
    "\n",
    "print('\\noutput rows and columns with probability')\n",
    "for element in update_list:\n",
    "    row, col = element[0]\n",
    "    probability = element[1]\n",
    "    print('row ', row, 'col ', col, 'probability ', probability)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Complete the Exercise\n",
    "\n",
    "Now complete the exercise, use the update_list to update the probabilities in the grid variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_probability(grid, update_list):\n",
    "\n",
    "    #### TODO:\n",
    "    # Use the update_list probabilities to update the probabilities in the grid variable. \n",
    "    # For example, if the grid is \n",
    "    \n",
    "    # grid = [[.05, .1, .1],\n",
    "    #    [.04, .3, .02],\n",
    "    #    [.01, .023, .017],\n",
    "    #    [.005, .012, .06],\n",
    "    #    [.09, .07, .103]]\n",
    "\n",
    "    # update_list = [[4, 2], 0.012]]\n",
    "    \n",
    "    # So the element in row 5, column 3 (remember Python does zero indexing) would be \n",
    "    # changed from 0.103 to 0.012\n",
    "    \n",
    "    return grid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now run the code below to test out your implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid = [[.05, .1, .1],\n",
    "        [.04, .3, .02],\n",
    "        [.01, .023, .017],\n",
    "        [.005, .012, .06],\n",
    "        [.09, .07, .103]]\n",
    "\n",
    "update_list = [\n",
    "              [[4,2], 0.012],\n",
    "              [[2,2], 0.108],\n",
    "              [[0,1], 0.004],\n",
    "              [[3,0], 0.101]\n",
    "              ]\n",
    "\n",
    "assert update_probability(grid, update_list) == [[0.05, 0.004, 0.1],\n",
    " [0.04, 0.3, 0.02],\n",
    " [0.01, 0.023, 0.108],\n",
    " [0.101, 0.012, 0.06],\n",
    " [0.09, 0.07, 0.012]]\n",
    "\n",
    "print('Nicely done')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
